package com.lin.filegraph.utils.model;

import com.lin.filegraph.utils.methoddg.MethodGraph;
import com.lin.filegraph.utils.calculator.CodeSizeCalculator;
import com.lin.filegraph.utils.parser.astvisitor.MethodMccabeVisitor;
import com.lin.filegraph.utils.parser.node.JMethodNode;

import java.util.List;

/**
 * @description:
 * @author: linhuaixu
 * @time: 2023/5/18 11:02
 */
public class MethodInfo implements Comparable<MethodInfo>{
    private JMethodNode methodNode;
    private String strComponentName = null;// �����
    private String strFilePath = null;
    private String strRelativeFilePath = null;
    private int LOC;// ������
    private int cyclomaticComplexity = 0;// Ȧ���Ӷ�
    private int maxCallDepth = 0;
    private String methodName = null;
    private int outDegreeInMDG = 0;// ����
    private int inDegreeInMDG = 0;// ���

    private boolean isAPI = false;// �Ƿ���API
    private boolean hasComment = false;// �Ƿ���ע��

    public MethodInfo(JMethodNode methodNode, String strComponentName) {
        super();
        this.methodNode = methodNode;
        this.strComponentName = strComponentName;
    }

    public MethodInfo(String methodName, int loc, Boolean isAPI, int inDegreeInMDG, int cyclomaticComplexity) {
        super();
        this.methodName = methodName;
        this.LOC = loc;
        this.isAPI = isAPI;
        this.inDegreeInMDG = inDegreeInMDG;
        this.cyclomaticComplexity = cyclomaticComplexity;
    }

    public JMethodNode getMethodNode() {
        return methodNode;
    }

    public void calculateMethodInfo() {
        // ������
        LOC = CodeSizeCalculator.calculateSizeOfNode(methodNode);
        // Ȧ���Ӷ�
        MethodMccabeVisitor methodMccabeVisitor = new MethodMccabeVisitor(methodNode);
        methodMccabeVisitor.traverseMethodContent();
        List<String> listMccabeOperators = methodMccabeVisitor.getListOperators();
        cyclomaticComplexity = listMccabeOperators.size();
        // ���������һ�����
        // �Ƿ���API
        isAPI = methodNode.isAPI();
        // �Ƿ���ע��
        hasComment = methodNode.isHasComment();
        // ��ȡ����ȡ����ò��
        MethodGraph mdg = methodNode.getRoot().getMdg();
        inDegreeInMDG = mdg.getPreMethods(methodNode).size();
        outDegreeInMDG = mdg.getPostMethods(methodNode).size();
        maxCallDepth = methodNode.getCallDepth();
        strFilePath = methodNode.getFilePath();
        strRelativeFilePath = methodNode.getFilePath().substring(methodNode.getRoot().getFilePath().length() + 1);
    }

    public void displayMethodInfo() {
        System.out.println("display method basic info ...");
        System.out.println(methodNode);
        System.out.println("LOC:" + LOC);
        System.out.println("strComponentName:" + strComponentName);
        System.out.println("Cyclomatic Complexity:" + cyclomaticComplexity);
        System.out.println("outDegreeInMDG:" + outDegreeInMDG);
        System.out.println("inDegreeInMDG:" + inDegreeInMDG);
        System.out.println("isAPI?:" + isAPI);
        System.out.println("hasComment?:" + hasComment);
        System.out.println("maxCallDepth:" + maxCallDepth);
    }

    public int getCyclomaticComplexity() {
        return cyclomaticComplexity;
    }

    public int getLOC() {
        return LOC;
    }

    public String getMethodName() {
        return this.methodName;
    }

    public int getOutDegreeInMDG() {
        return outDegreeInMDG;
    }

    public int getInDegreeInMDG() {
        return inDegreeInMDG;
    }

    public String getStrComponentName() {
        return strComponentName;
    }

    public boolean isAPI() {
        return isAPI;
    }

    public boolean isHasComment() {
        return hasComment;
    }

    public int getMaxCallDepth() {
        return maxCallDepth;
    }

    public String getStrFilePath() {
        return strFilePath;
    }

    public String getStrRelativeFilePath() {
        return strRelativeFilePath;
    }

    @Override
    public int compareTo(MethodInfo o) {
        if (this.inDegreeInMDG != o.inDegreeInMDG) {
            return this.inDegreeInMDG - o.inDegreeInMDG;
        } else {
            return this.cyclomaticComplexity - o.cyclomaticComplexity;
        }
    }
}

